package com.bims.jreport.document;

import cn.hutool.core.collection.CollUtil;
import com.bims.jreport.document.fields.*;
import com.bims.jreport.document.style.DocStyle;
import com.bims.jreport.pdf.CustomStyle;
import com.bims.jreport.document.table.DocTable;
import com.bims.jreport.document.table.cell.content.BaseContent;
import com.bims.jreport.document.table.setting.ExpandSetting;
import com.bims.jreport.document.table.cell.BaseCell;
import com.bims.jreport.document.table.setting.ExpandRow;
import com.bims.jreport.enums.PageEnum;
import com.bims.jreport.pdf.builder.BuilderContext;
import com.bims.jreport.pdf.CustomBody;
import com.bims.jreport.pdf.CustomImgData;
import com.bims.jreport.pdf.CustomOption;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.UnitValue;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bims.jreport.constant.ReportConstants.*;

/**
 * 文档模板
 *
 * @author wangrenjie
 */
@Getter
@Setter
public class DocTemplate implements Serializable {
    private static final long serialVersionUID = 7651077959402964656L;

    //页面信息
    private DocPageField page;

    //页眉
    private DocTagField header;

    //页脚
    private DocTagField footer;

    //全局配置属性
    private DocGlobalField global;

    //表格
    private List<DocTable> tables;

    //水印
    private DocWatermarkField watermark;

    //文档样式集
    private Map<String, DocStyle> styles;

    //文档图片集
    private Map<String, DocImageField> images;

    @JsonIgnore
    private BuilderContext context;


    /**
     * 转换全局设置内容
     * @return
     */
    public CustomOption fetchCustomOption() {
        return new CustomOption(global.getAutoCellHeight());
    }

    /**
     * 转换文档纸张属性
     *
     * @return
     */
    public PageSize fetchPageSize() {
        PageEnum pageEnum = PageEnum.valueOf(this.page.getSize());
        return pageEnum.getPageSize();
    }


    /**
     * 转换图片集对象
     *
     * @return
     */
    public Map<String, CustomImgData> fetchImageSet() {
        return images.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().fetchImageData()));
    }


    /***
     *  转换PDF样式
     * @return
     */
    public Map<String, CustomStyle> fetchStyleSet(){
        return styles.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().fetchStyle()));
    }

    /**
     * 转换表格内容
     *
     * @param context
     * @return
     */
    public List<CustomBody> fetchBody() {
        int pageIndex = 1;
        List<CustomBody> bodyList = new ArrayList<>();
        for (DocTable table : this.tables) {
            bodyList.add(this.convertTable(table, pageIndex));
            pageIndex++;
        }
        return bodyList;
    }

    /**
     * 将DOC对象转换成itext绘制所用的Table对象
     *
     * @return
     */
    private CustomBody convertTable(DocTable docTable, int pageIndex) {
        Table table = new Table(UnitValue.createPointArray(docTable.getCols())).useAllAvailableWidth();// N列的表格以及单元格的宽度。
        CustomBody customBody = new CustomBody(table, docTable.getBackgroundSetting());
        //TODO 是否需要再此设置宽高？
        Map<String, ExpandSetting> expandSettingMap = docTable.getSubform();
        //每一行的高度
        float[] rowHeights = docTable.getRows();
        BaseCell[][] cells = docTable.getCells();
        int rowNum = cells.length;
        if (rowNum <= 0) {
            return customBody;
        }
        //列总数
        int colNum = table.getNumberOfColumns();
        List<ExpandRow> expandRows = new ArrayList<>();
        for (int currentRow = 0; currentRow <= rowNum; currentRow++) {
            //处理扩展列
            if (CollUtil.isNotEmpty(expandRows)) {
                int expandRowNum = expandRows.stream().mapToInt(ExpandRow::getExpandNum).max().getAsInt();
                //绘制展开列内容
                this.drawExpandCell(table, expandRows, colNum, expandRowNum, pageIndex);
                //设置回循环次数
                rowNum -= expandRowNum;
                expandRows.clear();
                continue;
            }
            //处理非扩展列
            //一行数据
            ArrayList<BaseCell> rowCells = CollUtil.newArrayList(cells[currentRow]);
            //这一行中是否包含子表单
            int currentCol = CELL_START_COL_NUM;
            for (BaseCell rowCell : rowCells) {
                //处理展开内容
                if (rowCell.isSkip()) {
                    //跳过合并的子表单不绘制
                    currentCol++;
                    continue;
                }
                //先绘制单元格
                Cell cell = rowCell.convertCell(context.getStyleSet());
                //行高
                float rowHeight = rowHeights[currentRow];
                cell.setHeight(rowHeight);
                //然后绘制单元格内容
                BaseContent content = rowCell.getContent();
                String value = content.getValue();
                //是需要展开的类型 并且有子表单配置信息
                if (rowCell.needExpand() && expandSettingMap.containsKey(value)) {
                    //子表单最大行数
                    int maxPerPage = expandSettingMap.get(value).getMaxPerPage();
                    //生成子表单填充列
                    ExpandRow expandRow = new ExpandRow(currentCol, rowCell, maxPerPage, rowHeight);
                    expandRows.add(expandRow);
                }
                //绘制单元格内容
                content.fetchContent(this.context, cell, EXPAND_START_INDEX, pageIndex);
                table.addCell(cell);
                currentCol++;
            }
            //设置循环次数
            if (CollUtil.isNotEmpty(expandRows)) {
                rowNum += expandRows.stream().mapToInt(ExpandRow::getExpandNum).max().getAsInt();
            }

        }
        return customBody;
    }


    /**
     * 绘制扩展列单元格
     *
     * @param table        表格
     * @param expandRows   扩展列
     * @param colNum       总列数
     * @param expandRowNum 最大展开数
     * @param pageIndex    第几页
     */
    private void drawExpandCell(Table table, List<ExpandRow> expandRows, int colNum, int expandRowNum, int pageIndex) {
        Map<Integer, ExpandRow> expandRowMap = expandRows.stream().collect(Collectors.toMap(ExpandRow::getColNum, e -> e));
        for (int row = CELL_START_ROW_NUM; row <= expandRowNum; row++) {
            for (int col = CELL_START_COL_NUM; col <= colNum; col++) {
                if (expandRowMap.containsKey(col) && expandRowMap.get(col).getExpandNum() >= row) {
                    int expandIndex = EXPAND_START_INDEX + 1;
                    ExpandRow expandRow = expandRowMap.get(col);
                    //先绘制单元格
                    BaseCell rowCell = expandRow.getBaseCell();
                    Cell cell = rowCell.convertCell(context.getStyleSet());
                    cell.setHeight(expandRow.getRowHeight());
                    //然后绘制单元格内容
                    BaseContent content = rowCell.getContent();
                    //绘制单元格内容
                    content.fetchContent(this.context, cell, expandIndex, pageIndex);
                    table.addCell(cell);
                } else {
                    //TODO 填充默认空白单元格 样式？？
                    table.addCell(new Cell());
                }
            }
        }
    }
}
